package com.weiwen.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TimeZone;


/**
 * 日期操作工具�?
 * 
 * @author ht
 * @date 2010-3-24 15:30
 * @version 1.0      
 */
public class DateUtil {
	public static final String defaultDateFormat = "yyyy-MM-dd";
	public static final String defaultDateTimeFormat = "yyyy-MM-dd HH:mm:ss";

	/**
	 * Base ISO 8601 Date format yyyyMMdd i.e., 20021225 for the 25th day of
	 * December in the year 2002
	 */
	public static final String ISO_DATE_FORMAT = "yyyyMMdd";

	/**
	 * Expanded ISO 8601 Date format yyyy-MM-dd i.e., 2002-12-25 for the 25th
	 * day of December in the year 2002
	 */
	public static final String ISO_EXPANDED_DATE_FORMAT = "yyyy-MM-dd";

	/**
	 * yyyy-MM-dd hh:mm:ss
	 */
	public static String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

	/**
	 * Default lenient setting for getDate.
	 */
	private static boolean LENIENT_DATE = false;

	private static Random random = new java.util.Random();
	private static final int ID_BYTES = 10;

	public synchronized static String generateId() {
		StringBuffer result = new StringBuffer();
		result = result.append(System.currentTimeMillis());
		for (int i = 0; i < ID_BYTES; i++) {
			result = result.append(random.nextInt(10));
		}
		return result.toString();
	}

	protected static final float normalizedJulian(float JD) {

		float f = Math.round(JD + 0.5f) - 0.5f;

		return f;
	}

	/**
	 * Returns the Date from a julian. The Julian date will be converted to noon
	 * GMT, such that it matches the nearest half-integer (i.e., a julian date
	 * of 1.4 gets changed to 1.5, and 0.9 gets changed to 0.5.)
	 * 
	 * @param JD
	 *            the Julian date
	 * @return the Gregorian date
	 */
	public static final Date toDate(float JD) {

		/*
		 * To convert a Julian Day Number to a Gregorian date, assume that it is
		 * for 0 hours, Greenwich time (so that it ends in 0.5). Do the
		 * following calculations, again dropping the fractional part of all
		 * multiplicatons and divisions. Note: This method will not give dates
		 * accurately on the Gregorian Proleptic Calendar, i.e., the calendar
		 * you get by extending the Gregorian calendar backwards to years
		 * earlier than 1582. using the Gregorian leap year rules. In
		 * particular, the method fails if Y<400.
		 */
		float Z = (normalizedJulian(JD)) + 0.5f;
		float W = (int) ((Z - 1867216.25f) / 36524.25f);
		float X = (int) (W / 4f);
		float A = Z + 1 + W - X;
		float B = A + 1524;
		float C = (int) ((B - 122.1) / 365.25);
		float D = (int) (365.25f * C);
		float E = (int) ((B - D) / 30.6001);
		float F = (int) (30.6001f * E);
		int day = (int) (B - D - F);
		int month = (int) (E - 1);

		if (month > 12) {
			month = month - 12;
		}

		int year = (int) (C - 4715); // (if Month is January or February) or
										// C-4716 (otherwise)

		if (month > 2) {
			year--;
		}

		Calendar c = Calendar.getInstance();
		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, month - 1); // damn 0 offsets
		c.set(Calendar.DATE, day);

		return c.getTime();
	}

	/**
	 * Returns the days between two dates. Positive values indicate that the
	 * second date is after the first, and negative values indicate, well, the
	 * opposite. Relying on specific times is problematic.
	 * 
	 * @param early
	 *            the "first date"
	 * @param late
	 *            the "second date"
	 * @return the days between the two dates
	 */
	public static final int daysBetween(Date early, Date late) {

		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.setTime(early);
		c2.setTime(late);

		return daysBetween(c1, c2);
	}

	/**
	 * Returns the days between two dates. Positive values indicate that the
	 * second date is after the first, and negative values indicate, well, the
	 * opposite.
	 * 
	 * @param early
	 * @param late
	 * @return the days between two dates.
	 */
	public static final int daysBetween(Calendar early, Calendar late) {

		return (int) (toJulian(late) - toJulian(early));
	}

	/**
	 * Return a Julian date based on the input parameter. This is based from
	 * calculations found at <a
	 * href="http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html">Julian Day
	 * Calculations (Gregorian Calendar)</a>, provided by Bill Jeffrys.
	 * 
	 * @param c
	 *            a calendar instance
	 * @return the julian day number
	 */
	public static final float toJulian(Calendar c) {

		int Y = c.get(Calendar.YEAR);
		int M = c.get(Calendar.MONTH);
		int D = c.get(Calendar.DATE);
		int A = Y / 100;
		int B = A / 4;
		int C = 2 - A + B;
		float E = (int) (365.25f * (Y + 4716));
		float F = (int) (30.6001f * (M + 1));
		float JD = C + D + E + F - 1524.5f;

		return JD;
	}

	/**
	 * Return a Julian date based on the input parameter. This is based from
	 * calculations found at <a
	 * href="http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html">Julian Day
	 * Calculations (Gregorian Calendar)</a>, provided by Bill Jeffrys.
	 * 
	 * @param date
	 * @return the julian day number
	 */
	public static final float toJulian(Date date) {

		Calendar c = Calendar.getInstance();
		c.setTime(date);

		return toJulian(c);
	}

	/**
	 * @param isoString
	 * @param fmt
	 * @param field
	 *            Calendar.YEAR/Calendar.MONTH/Calendar.DATE
	 * @param amount
	 * @return
	 * @throws ParseException
	 */
	public static final String dateIncrease(String isoString, String fmt,
			int field, int amount) {

		try {
			Calendar cal = Calendar.getInstance(TimeZone
					.getTimeZone("GMT"));
			cal.setTime(stringToDate(isoString, fmt, true));
			cal.add(field, amount);

			return dateToString(cal.getTime(), fmt);

		} catch (Exception ex) {
			return null;
		}
	}

	/**
	 * Time Field Rolling function. Rolls (up/down) a single unit of time on the
	 * given time field.
	 * 
	 * @param isoString
	 * @param field
	 *            the time field.
	 * @param up
	 *            Indicates if rolling up or rolling down the field value.
	 * @param expanded
	 *            use formating char's
	 * @exception ParseException
	 *                if an unknown field value is given.
	 */
	public static final String roll(String isoString, String fmt, int field,
			boolean up) throws ParseException {

		Calendar cal = Calendar.getInstance(TimeZone
				.getTimeZone("GMT"));
		cal.setTime(stringToDate(isoString, fmt));
		cal.roll(field, up);

		return dateToString(cal.getTime(), fmt);
	}

	/**
	 * Time Field Rolling function. Rolls (up/down) a single unit of time on the
	 * given time field.
	 * 
	 * @param isoString
	 * @param field
	 *            the time field.
	 * @param up
	 *            Indicates if rolling up or rolling down the field value.
	 * @exception ParseException
	 *                if an unknown field value is given.
	 */
	public static final String roll(String isoString, int field, boolean up)
			throws ParseException {

		return roll(isoString, DATETIME_PATTERN, field, up);
	}

	/**
	 * java.util.Date
	 * 
	 * @param dateText
	 * @param format
	 * @param lenient
	 * @return
	 */
	public static Date stringToDate(String dateText, String format,
			boolean lenient) {

		if (dateText == null) {

			return null;
		}

		DateFormat df = null;

		try {

			if (format == null) {
				df = new SimpleDateFormat();
			} else {
				df = new SimpleDateFormat(format);
			}

			// setLenient avoids allowing dates like 9/32/2001
			// which would otherwise parse to 10/2/2001
			df.setLenient(false);

			return df.parse(dateText);
		} catch (ParseException e) {

			return null;
		}
	}

	/**
	 * @return Timestamp
	 */
	public static java.sql.Timestamp getCurrentTimestamp() {
		return new java.sql.Timestamp(new java.util.Date().getTime());
	}

	/**
	 * java.util.Date
	 * 
	 * @param dateText
	 * @param format
	 * @return
	 */
	public static Date stringToDate(String dateString, String format) {

		return stringToDate(dateString, format, LENIENT_DATE);
	}

	/**
	 * java.util.Date
	 * 
	 * @param dateText
	 */
	public static Date stringToDate(String dateString) {
		return stringToDate(dateString, defaultDateTimeFormat, LENIENT_DATE);
	}

	/**
	 * @return
	 * @param pattern
	 * @param date
	 */
	public static String dateToString(Date date, String pattern) {

		if (date == null) {
			return null;
		}

		try {

			SimpleDateFormat sfDate = new SimpleDateFormat(pattern);
			sfDate.setLenient(false);

			return sfDate.format(date);
		} catch (Exception e) {

			return null;
		}
	}

	/**
	 * yyyy-MM-dd
	 * 
	 * @param date
	 * @return
	 */
	public static String dateToString(Date date) {
		return dateToString(date, ISO_EXPANDED_DATE_FORMAT);
	}

	/**
	 * @return
	 */
	public static Date getCurrentDateTime() {
		java.util.Calendar calNow = java.util.Calendar.getInstance();
		java.util.Date dtNow = calNow.getTime();

		return dtNow;
	}

	/**
	 * 
	 * @param pattern
	 * @return
	 */
	public static String getCurrentDateString(String pattern) {
		return dateToString(getCurrentDateTime(), pattern);
	}

	/**
	 * yyyy-MM-dd
	 * 
	 * @return
	 */
	public static String getCurrentDateString() {
		return dateToString(getCurrentDateTime(), ISO_EXPANDED_DATE_FORMAT);
	}

	/**
	 * yyyy-MM-dd hh:mm:ss
	 * 
	 * @param date
	 * @return
	 */
	public static String dateToStringWithTime(Date date) {

		return dateToString(date, DATETIME_PATTERN);
	}

	/**
	 * 
	 * @param date
	 * @param days
	 * @return java.util.Date
	 */
	public static Date dateIncreaseByDay(Date date, int days) {

		Calendar cal = Calendar.getInstance(TimeZone
				.getTimeZone("GMT"));
		cal.setTime(date);
		cal.add(Calendar.DATE, days);

		return cal.getTime();
	}

	/**
	 * 
	 * @param date
	 * @param days
	 * @return java.util.Date
	 */
	public static Date dateIncreaseByMonth(Date date, int mnt) {

		Calendar cal = Calendar.getInstance(TimeZone
				.getTimeZone("GMT"));
		cal.setTime(date);
		cal.add(Calendar.MONTH, mnt);

		return cal.getTime();
	}

	/**
	 * 
	 * @param date
	 * @param mnt
	 * @return java.util.Date
	 */
	public static Date dateIncreaseByYear(Date date, int mnt) {

		Calendar cal = Calendar.getInstance(TimeZone
				.getTimeZone("GMT"));
		cal.setTime(date);
		cal.add(Calendar.YEAR, mnt);

		return cal.getTime();
	}

	/**
	 * 
	 * @param date
	 *            yyyy-MM-dd
	 * @param days
	 * @return yyyy-MM-dd
	 */
	public static String dateIncreaseByDay(String date, int days) {
		return dateIncreaseByDay(date, ISO_DATE_FORMAT, days);
	}

	/**
	 * @param date
	 * @param fmt
	 * @param days
	 * @return
	 */
	public static String dateIncreaseByDay(String date, String fmt, int days) {
		return dateIncrease(date, fmt, Calendar.DATE, days);
	}

	/**
	 * 
	 * @param src
	 * @param srcfmt
	 * @param desfmt
	 * @return
	 */
	public static String stringToString(String src, String srcfmt, String desfmt) {
		return dateToString(stringToDate(src, srcfmt), desfmt);
	}

	/**
	 * 
	 * @param date
	 * @return string
	 */
	public static String getYear(Date date) {
		java.text.SimpleDateFormat formater = new java.text.SimpleDateFormat(
				"yyyy");
		String cur_year = formater.format(date);
		return cur_year;
	}

	/**
	 * 
	 * @param date
	 * @return string
	 */
	public static String getMonth(Date date) {
		java.text.SimpleDateFormat formater = new java.text.SimpleDateFormat(
				"MM");
		String cur_month = formater.format(date);
		return cur_month;
	}

	/**
	 * @param date
	 * @return string
	 */
	public static String getDay(Date date) {
		java.text.SimpleDateFormat formater = new java.text.SimpleDateFormat(
				"dd");
		String cur_day = formater.format(date);
		return cur_day;
	}

	public static int getMinsFromDate(java.util.Date dt) {
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTime(dt);
		int hour = cal.get(Calendar.HOUR_OF_DAY);
		int min = cal.get(Calendar.MINUTE);
		return ((hour * 60) + min);
	}

	/**
	 * Function to convert String to Date Object. If invalid input then current
	 * or next day date is returned (Added by Ali Naqvi on 2006-5-16).
	 * 
	 * @param str
	 *            String input in YYYY-MM-DD HH:MM[:SS] format.
	 * @param isExpiry
	 *            boolean if set and input string is invalid then next day date
	 *            is returned
	 * @return Date
	 */
	public static java.util.Date convertToDate(String str, boolean isExpiry) {
		SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		java.util.Date dt = null;
		try {
			dt = fmt.parse(str);
		} catch (ParseException ex) {
			Calendar cal = Calendar.getInstance();
			if (isExpiry) {
				cal.add(Calendar.DAY_OF_MONTH, 1);
				cal.set(Calendar.HOUR_OF_DAY, 23);
				cal.set(Calendar.MINUTE, 59);
			} else {
				cal.set(Calendar.HOUR_OF_DAY, 0);
				cal.set(Calendar.MINUTE, 0);
			}
			dt = cal.getTime();
		}
		return dt;
	}

	public static java.util.Date convertToDate(String str) {
		SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd hh:mm");
		java.util.Date dt = null;
		try {
			dt = fmt.parse(str);
		} catch (ParseException ex) {
			dt = new java.util.Date();
		}
		return dt;
	}

	public static String dateFromat(Date date, int minute) {
		String dateFormat = null;
		int year = Integer.parseInt(getYear(date));
		int month = Integer.parseInt(getMonth(date));
		int day = Integer.parseInt(getDay(date));
		int hour = minute / 60;
		int min = minute % 60;
		dateFormat = String.valueOf(year)
				+ (month > 9 ? String.valueOf(month) : "0"
						+ String.valueOf(month))
				+ (day > 9 ? String.valueOf(day) : "0" + String.valueOf(day))
				+ " "
				+ (hour > 9 ? String.valueOf(hour) : "0" + String.valueOf(hour))
				+ (min > 9 ? String.valueOf(min) : "0" + String.valueOf(min))
				+ "00";
		return dateFormat;
	}

	/**
	 * 格式化日�?
	 * 
	 * @param FormatStr
	 *            格式化格�?
	 * @param date
	 *            Date
	 * @return
	 */
	public static final String FormatDatetime(String FormatStr, Date date) {
		SimpleDateFormat bartDateFormat = new SimpleDateFormat(FormatStr);
		return (date == null) ? "" : bartDateFormat.format(date);
	}

	/**
	 * 格式化当前日�?
	 * 
	 * @param FormatStr
	 *            格式化格�?
	 * @return
	 */
	public static final String FormatDatetime(String FormatStr) {
		SimpleDateFormat bartDateFormat = new SimpleDateFormat(FormatStr);
		return bartDateFormat.format(new Date());
	}

	/**
	 * 把Date转换为字符串
	 * 
	 * @param date
	 *            Date
	 * @return yyyy-MM-dd HH:mm:ss
	 */
	public static final String DatetimetoStr(Date date) {
		SimpleDateFormat bartDateFormat = new SimpleDateFormat(
				defaultDateTimeFormat);
		return bartDateFormat.format(date);
	}

	/**
	 * 把字符串日期转换为Date
	 * 
	 * @param ADate
	 *            yyyy-MM-dd
	 * @return Date
	 * @throws Exception
	 */
	public static final Date StrtoDate(String ADate) throws Exception {
		return StrtoDate(ADate, "-");
	}

	/**
	 * 把字符串日期转换为Date
	 * 
	 * @param ADate
	 *            yyyy-MM-dd
	 * @param ListSeparator
	 *            分隔�?
	 * @return Date
	 * @throws Exception
	 */
	public static final Date StrtoDate(String ADate, String ListSeparator)
			throws Exception {
		if ((ADate == null) || (ADate.length() == 0)) {
			return new java.util.Date();
		} else {
			StringTokenizer st = new StringTokenizer(ADate, ListSeparator);
			if (st.countTokens() != 3) {
				throw new Exception("date format error!");
			} else {

				int Year = Integer.parseInt(st.nextToken());
				int Month = Integer.parseInt(st.nextToken());
				int Day = Integer.parseInt(st.nextToken());

				Calendar cale = Calendar.getInstance();
				cale.set(Calendar.YEAR, Year);
				cale.set(Calendar.MONTH, Month - 1);
				cale.set(Calendar.DATE, Day);
				return cale.getTime();
			}
		}
	}

	/**
	 * 把Date转换为字符串
	 * 
	 * @param date
	 *            Date
	 * @return yyyy-MM-dd
	 */
	public static final String DatetoStr(Date date) {
		SimpleDateFormat bartDateFormat = new SimpleDateFormat(
				defaultDateFormat);
		return (date == null) ? "" : bartDateFormat.format(date);
	}

	/**
	 * 获得当前日期
	 * 
	 * @return
	 */
	public static final Date Now() {
		return new Date();
	}

	/**
	 * 获得当前日期字符�?
	 * 
	 * @return yyyy-MM-dd HH:mm:ss
	 */
	public static final String NowStr() {
		return DatetimetoStr(new Date());
	}

	/**
	 * 获得当前日期字符�?
	 * 
	 * @return yyyy-MM-dd
	 */
	public static final String DateStr() {
		return DatetoStr(new Date());
	}

	/**
	 * 获得当前日期long time
	 * 
	 * @return
	 */
	public static final String getTime() {
		return String.valueOf(new Date().getTime());
	}

	/**
	 * 获得当前秒数
	 * 
	 * @return
	 */
	public static final String getSecond() {
		return getTime().substring(0, 10);
	}

	/**
	 * 获得当前年份
	 * 
	 * @return
	 */
	public static final String getStrCurrYear() {
		return (DateUtil.FormatDatetime("yyyy", new Date()));
	}

	/**
	 * 当前年份-3
	 * 
	 * @return
	 */
	public static final String getStrYear() {
		return ((Integer.parseInt(DateUtil.FormatDatetime("yyyy", new Date())) - 3) + "");
	}

	/**
	 * 获得当前string月份
	 * 
	 * @return
	 */
	public static final String getStrCurrMonth() {
		return (DateUtil.FormatDatetime("MM", new Date()));
	}

	/**
	 * 获得当前string�?
	 * 
	 * @return
	 */
	public static final String getStrCurrDay() {
		return (DateUtil.FormatDatetime("dd", new Date()));
	}

	/**
	 * 获得当前string小时
	 * 
	 * @return
	 */
	public static final String getStrCurrHour() {
		return (DateUtil.FormatDatetime("HH", new Date()));
	}

	/**
	 * 获得当前string分钟
	 * 
	 * @return
	 */
	public static final String getStrCurrMinute() {
		return (DateUtil.FormatDatetime("mm", new Date()));
	}

	/**
	 * 获得当前int年份
	 * 
	 * @return
	 */
	public static final int getIntCurrYear() {
		return (Integer.parseInt(getStrCurrYear()));
	}

	/**
	 * 获得当前int月份
	 * 
	 * @return
	 */
	public static final int getIntCurrMonth() {
		return (Integer.parseInt(getStrCurrMonth()));
	}

	/**
	 * 获得当前int�?
	 * 
	 * @return
	 */
	public static final int getIntCurrDay() {
		return (Integer.parseInt(getStrCurrDay()));
	}

	/**
	 * 获得当前int小时
	 * 
	 * @return
	 */
	public static final int getIntCurrHour() {
		return (Integer.parseInt(getStrCurrHour()));
	}

	/**
	 * 获得当前int分钟
	 * 
	 * @return
	 */
	public static final int getIntCurrMinute() {
		return (Integer.parseInt(getStrCurrMinute()));
	}

	/**
	 * 获得当前季度
	 * 
	 * @return
	 */
	public int getSeason() {
		int month = getIntCurrMonth();

		if (1 <= month && month <= 3) {
			return (1);
		} else if (4 <= month && month <= 6) {
			return (2);
		} else if (7 <= month && month <= 9) {
			return (3);
		} else {
			return (4);
		}
	}

	/**
	 * 获得给定日期的前或后几天（num>0 前，<0后）
	 * 
	 * @return
	 * @throws ParseException
	 */
	public static final String getDayBeforeOrAfter(String yourDate, int num)
			throws ParseException {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		Date yourTime = df.parse(yourDate + " 00:00:00");
		long nowTime = yourTime.getTime() - 1000 * 3600 * 24 * num;
		Date newDate = new Date(nowTime);

		return DateUtil.FormatDatetime(DateUtil.defaultDateFormat, newDate);
	}

	/**
	 * 把时间格式化为标准的日期时间格式
	 * 
	 * @return
	 * @throws ParseException
	 */
	public static final String getFormatToDateTime(String datetime)
			throws ParseException {
		String str = "";
		if (datetime.indexOf(".") > 0) {
			str = datetime.substring(0, datetime.indexOf("."));
		} else {
			str = datetime;
		}

		return str;
	}

	/**
	 * 日期处理--截取日期yyyy-MM-dd hh:mm
	 * 
	 * @param 带秒的字符型日期
	 * @return 去掉秒的字符型日�?调用方式：DateUtil.dateDeal("字符型日�?);
	 */
	public static String dateDeal(String para) {
		StringBuffer sb = new StringBuffer();
		sb.append(para.split(":")[0] + ":" + para.split(":")[1]);
		return sb.toString();
	}
	

	/**
	 * 把两个日期相�?
	 * @param sy			起点�?
	 * @param sm			起点�?
	 * @param sd			起点�?
	 * @param sh			起点小时
	 * @param smm			起点分钟
	 * @param ss			起点�?
	 * @param ey			终点�?
	 * @param em			终点�?
	 * @param ed			终点�?
	 * @param eh			终点小时
	 * @param emm			终点分钟
	 * @param es			终点�?
	 * @return
	 */
	public long getSubTime(int sy,int sm,int sd,int sh,int smm,int ss,int ey,int em,int ed,int eh,int emm,int es)
	{
		GregorianCalendar t1 = new GregorianCalendar(sy,sm,sd,sh,smm,ss); 
		GregorianCalendar t2 = new GregorianCalendar(ey,em,ed,eh,emm,es); 
		
		long st = t2.getTimeInMillis()-t1.getTimeInMillis();
		
		return(st/1000);
	}

	public static void main(String args[]) {

	}

	public static boolean before(String time, String format) {
		SimpleDateFormat sf = new SimpleDateFormat(format);
		try {
			Date da = sf.parse(time);
			Date now = sf.parse(sf.format(new Date()));
			// 日期比较
			return da.before(now);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean after(String time, String format) {
		SimpleDateFormat sf = new SimpleDateFormat(format);
		try {
			Date da = sf.parse(time);
			Date now = sf.parse(sf.format(new Date()));
			// 日期比较
			return da.after(now);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return false;
	}
	public static boolean checkDateStr(String date){
		if(date==null){
			return false;
		}
		else
		{
			return date.matches("[0-9]{4}-[0-1]{1}[0-9]{1}-[0-3]{1}[0-9]{1}\\s[0-2]{1}[0-9]{1}:[0-6]{1}[0-9]{1}:[0-6]{1}[0-9]{1}");
		}
		
	}
	

	
}
